package com.cuixichang.minimalism.domain;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cuixichang.minimalism.acl.RelevanceDesign;
import com.cuixichang.minimalism.basal.enums.DefaultNumberEnum;
import com.cuixichang.minimalism.core.mybatis.cnstants.BaseFieldNames;
import com.cuixichang.minimalism.core.security.userdetails.CredentialDetail;
import com.cuixichang.minimalism.service.*;
import com.cuixichang.minimalism.transfer.dto.*;
import com.cuixichang.minimalism.transfer.po.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class IPermissionCommandServiceImpl implements IPermissionCommandService{
    @Autowired
    private IPermissionService iPermissionService;
    @Autowired
    private IRolePermissionService rolePermissionService;
    @Autowired
    private RelevanceDesign relevanceDesign;
    @Autowired
    private IRouterService routerService;
    @Autowired
    private IRouterRelationService routerRelationService;

    @Override
    public IPermissionDTO insert(IPermissionDTO permissionDTO, CredentialDetail credentialDetail) {
        Assert.notNull(permissionDTO,"插入权限参数为空,请检查");
        String permissionCode = permissionDTO.getPermissionCode();
        Assert.hasText(permissionCode,"权限编码不能为空,请检查");
        String createSystemCode = permissionDTO.getCreateSystemCode();
        Assert.hasText(createSystemCode,"系统编码不能为空,请检查");
        permissionDTO.setCreateLoginId(Objects.isNull(credentialDetail)? DefaultNumberEnum.Zero.getCode() :credentialDetail.getLoginId());
        IPermissionDTO iPermission = iPermissionService.insertHasOption(permissionDTO, dto ->
                iPermissionService.selectOne(IPermissionDTO.builder().permissionCode(dto.getPermissionCode())
                        .createSystemCode(dto.getCreateSystemCode()).build()));
        Assert.notNull(iPermission,"插入权限信息失败,请联系管理员");
        return iPermission;
    }

    @Override
    public IPermissionDTO selectByIdHasPreCheck(Long id, String systemCode, CredentialDetail credentialDetail) {
        Assert.notNull(id,"权限Id不能为空,请检查");
        Assert.hasText(systemCode,"系统编码不能为空,请检查");
        return Optional.ofNullable(credentialDetail).map(credential -> {
            List<Long> beAuthLoginIds = relevanceDesign.beAuthLoginIds(credential.getLoginId());
            IPermissionDTO iPermission = iPermissionService.selectById(id);
            return Optional.ofNullable(iPermission).filter(permission -> beAuthLoginIds.contains(permission.getCreateLoginId()))
                    .orElse(null);
        }).orElse(iPermissionService.selectById(id));
    }

    @Override
    public IPermissionDTO selectByCodeHasPreCheck(String permissionCode, String systemCode, CredentialDetail credentialDetail) {
        Assert.hasText(permissionCode,"权限编码不能为空,请检查");
        Assert.hasText(systemCode,"系统编码不能为空,请检查");
        return Optional.ofNullable(credentialDetail).map(credential -> {
            List<Long> beAuthLoginIds = relevanceDesign.beAuthLoginIds(credential.getLoginId());
            IPermissionDTO iPermission = iPermissionService.selectOne(IPermissionDTO.builder().permissionCode(permissionCode)
                    .createSystemCode(systemCode).build());
            return Optional.ofNullable(iPermission).filter(permission -> beAuthLoginIds.contains(permission.getCreateLoginId()))
                .orElse(null);
        }).orElse(iPermissionService.selectOne(IPermissionDTO.builder().permissionCode(permissionCode)
                    .createSystemCode(systemCode).build()));
    }

    @Override
    public boolean deleteByIdHasPreCheck(Long id, String systemCode, CredentialDetail credentialDetail) {
        IPermissionDTO permission = selectByIdHasPreCheck(id, systemCode, credentialDetail);
        if(Objects.isNull(permission)) return false;
        return iPermissionService.deleteById(id) == 1 ;
    }

    @Override
    public boolean updateByIdHasPreCheck(IPermissionDTO permissionDTO, CredentialDetail credentialDetail) {
        Assert.notNull(permissionDTO,"权限信息不能为空,请检查");
        Long id = permissionDTO.getId();
        Assert.notNull(id,"权限Id不能为空,请检查");
        String createSystemCode = permissionDTO.getCreateSystemCode();
        Assert.hasText(createSystemCode,"系统编码不能为空,请检查");
        IPermissionDTO permission = selectByIdHasPreCheck(id, createSystemCode, credentialDetail);
        if(Objects.isNull(permission)) return false;
        permissionDTO.setCreateLoginId(Objects.isNull(credentialDetail)?0L:credentialDetail.getLoginId());
        return iPermissionService.updateById(permissionDTO) == 1;
    }

    @Override
    public List<IPermissionDTO> rolesHasBindingPermissions(IPermissionDTO permissionDTO,String systemCode,List<Long> roleIds) {
        Assert.notNull(permissionDTO,"查询权限信息参数为空,请检查");
        permissionDTO.setCreateSystemCode(systemCode);
        Assert.notEmpty(roleIds,"查询角色Id集合参数为空,请检查");
        List<IRolePermissionDTO> iRolePermissions = rolePermissionService.selectList(IRolePermissionDTO.builder().isEnable(true).build(),
                (rolePermission, queryWrapper) -> queryWrapper.in("role_id", roleIds));
        if(CollectionUtils.isEmpty(iRolePermissions)) return Collections.emptyList();
        List<Long> hasBindingPermissionIds = iRolePermissions.stream().map(IL -> IL.getPermissionId()).distinct().collect(Collectors.toList());
        return iPermissionService.selectList(permissionDTO,(iPermission, queryWrapper) -> queryWrapper.in(BaseFieldNames.ID,hasBindingPermissionIds));
    }

    @Override
    public Page<IPermissionDTO> selectPageByConditional(IPermissionDTO permissionDTO, Long pageNo, Long pageSize, CredentialDetail credentialDetail) {
        if(Objects.isNull(credentialDetail)) return Page.of(pageNo,pageSize);
        Long createLoginId = credentialDetail.getLoginId();
        return iPermissionService.selectPage(permissionDTO,pageSize,pageNo,(iPermission, queryWrapper)->{
            if(Objects.nonNull(createLoginId)){
                List<Long> beAuthLoginIds = relevanceDesign.beAuthLoginIds(createLoginId);
                queryWrapper.in(!CollectionUtils.isEmpty(beAuthLoginIds), BaseFieldNames.CREATE_LOGIN_ID, beAuthLoginIds);
            }
            processBindingPermissionQueryWrapper(queryWrapper,permissionDTO.getKeyword());
        });
    }

    @Override
    public Page<IPermissionDTO> roleHasBindingPermissions(IPermissionDTO permissionDTO, Long pageNo, Long pageSize, Long roleId, CredentialDetail credentialDetail) {
        checkPageQuery(permissionDTO, pageNo, pageSize);
        Assert.notNull(roleId,"查询角色Id为空,请检查");
        List beAuthLoginIds = Optional.ofNullable(credentialDetail).map(credential -> relevanceDesign.beAuthLoginIds(credential.getLoginId()))
                .orElse(Collections.EMPTY_LIST);
        IRoleDTO role = relevanceDesign.checkRole(roleId, beAuthLoginIds, credentialDetail);
        Page<IPermissionDTO> result = new Page<>(pageNo,pageSize);
        if(Objects.isNull(role)) return result;
        List<IRolePermissionDTO> iRoleMenus = rolePermissionService.selectList(IRolePermissionDTO.builder().roleId(role.getId()).isEnable(true).build());
        List<Long> permissionIds = iRoleMenus.stream().map(IRolePermissionDTO::getPermissionId).distinct().collect(Collectors.toList());
        if(CollectionUtils.isEmpty(permissionIds)) return result;
        return iPermissionService.selectPage(permissionDTO,pageSize,pageNo,(iPermission, queryWrapper) -> {
            queryWrapper.in(BaseFieldNames.ID,permissionIds);
            processBindingPermissionQueryWrapper(queryWrapper,permissionDTO.getKeyword());
        });
    }

    @Override
    public Page<IPermissionDTO> roleUnBindingPermissions(IPermissionDTO permissionDTO, Long pageNo, Long pageSize, Long roleId, CredentialDetail credentialDetail) {
        checkPageQuery(permissionDTO, pageNo, pageSize);
        Assert.notNull(roleId,"查询角色Id为空,请检查");
        Page<IPermissionDTO> result = new Page(pageNo,pageSize);
        return Optional.ofNullable(credentialDetail).map(credential -> {
            List<Long> beAuthLoginIds = relevanceDesign.beAuthLoginIds(credential.getLoginId());
            IRoleDTO role = relevanceDesign.checkRole(roleId, beAuthLoginIds, credentialDetail);
            if(Objects.isNull(role)) return result;
            List<IRolePermissionDTO> iRoleMenus = rolePermissionService.selectList(IRolePermissionDTO.builder().roleId(role.getId()).isEnable(true).build());
            List<Long> permissionIds = iRoleMenus.stream().map(IRolePermissionDTO::getPermissionId).distinct().collect(Collectors.toList());
            return iPermissionService.selectPage(permissionDTO,pageSize,pageNo,(iMenu, queryWrapper)->{
                queryWrapper.in(BaseFieldNames.CREATE_LOGIN_ID, beAuthLoginIds);
                queryWrapper.notIn(!CollectionUtils.isEmpty(permissionIds),BaseFieldNames.ID,permissionIds);
                processBindingPermissionQueryWrapper(queryWrapper,permissionDTO.getKeyword());
            });
        }).orElse(result);
    }

    @Override
    public Page<IPermissionDTO> routerHasBindingPermissions(IPermissionDTO dto, Long pageNo, Long pageSize, Long routerId, CredentialDetail credentialDetail) {
        checkPageQuery(dto, pageNo, pageSize);
        Assert.notNull(routerId,"查询路由Id为空,请检查");
        IRouterDTO po = Optional.ofNullable(credentialDetail).map(credential ->
            routerService.selectList(IRouterDTO.builder().build(), (var, queryWrapper) -> {
            queryWrapper.eq(BaseFieldNames.ID, routerId);
            List<Long> beAuthLoginIds = relevanceDesign.beAuthLoginIds(credential.getLoginId());
            queryWrapper.in(!CollectionUtils.isEmpty(beAuthLoginIds), BaseFieldNames.CREATE_LOGIN_ID, beAuthLoginIds);
        }).stream().findFirst().orElse(null)).orElseGet(() -> routerService.selectById(routerId));
        Page<IPermissionDTO> result = new Page(pageNo,pageSize);
        if(Objects.isNull(po)) return result;
        List<IRouterRelationDTO> relations = routerRelationService.selectList(IRouterRelationDTO.builder().routerId(po.getId())
                .roleRelation(false).isEnable(true).build());
        List<Long> relationIds = relations.stream().map(IRouterRelationDTO::getRelationId).distinct().collect(Collectors.toList());
        if(CollectionUtils.isEmpty(relationIds)) return result;
         return iPermissionService.selectPage(dto,pageSize,pageNo,(iPermission, queryWrapper) -> {
            queryWrapper.in(BaseFieldNames.ID,relationIds);
            processBindingPermissionQueryWrapper(queryWrapper,dto.getKeyword());
        });
    }

    @Override
    public Page<IPermissionDTO> routerUnBindingPermissions(IPermissionDTO dto, Long pageNo, Long pageSize, Long routerId, CredentialDetail credentialDetail) {
        checkPageQuery(dto, pageNo, pageSize);
        Assert.notNull(routerId,"查询路由Id为空,请检查");
        Page<IPermissionDTO> result = new Page<IPermissionDTO>(pageNo, pageSize);
        return Optional.ofNullable(credentialDetail).map(credential -> {
            List<Long> beAuthLoginIds = relevanceDesign.beAuthLoginIds(credential.getLoginId());
            IRouterDTO router = Optional.ofNullable(routerService.selectById(routerId)).
                    filter(r -> beAuthLoginIds.contains(r.getCreateLoginId())).orElse(null);
            if(Objects.isNull(router)) return result;
            List<Long> relationIds = routerRelationService.selectList(IRouterRelationDTO.builder().routerId(routerId).isEnable(true)
                    .roleRelation(false).build()).stream().map(IRouterRelationDTO::getRelationId).distinct().collect(Collectors.toList());
            return iPermissionService.selectPage(dto,pageSize,pageNo,(iMenu, queryWrapper)->{
                queryWrapper.in(BaseFieldNames.CREATE_LOGIN_ID, beAuthLoginIds);
                queryWrapper.notIn(!CollectionUtils.isEmpty(relationIds),BaseFieldNames.ID,relationIds);
                processBindingPermissionQueryWrapper(queryWrapper,dto.getKeyword());
            });
        }).orElse(result);
    }

    private void checkPageQuery(IPermissionDTO dto, Long pageNo, Long pageSize){
        Assert.notNull(dto,"权限信息不能为空,请检查");
        Assert.notNull(dto.getCreateSystemCode(),"系统编码不能为空");
        Assert.notNull(pageNo,"页码不能为空");
        Assert.notNull(pageSize,"页大小不能为空");
    }

    private void processBindingPermissionQueryWrapper(QueryWrapper<IPermission> queryWrapper,String keyword){
        queryWrapper.and(StrUtil.isNotBlank(keyword),(wrapper)->{
            wrapper.like("permission_name",keyword);
            wrapper.or().like("permission_code",keyword);
            wrapper.or().like("permission_signboard",keyword);
        });
    }
}
